package com.ftf.tp.blog.application.service.command.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.ftf.tp.blog.application.assembler.CommentAssembler;
import com.ftf.tp.blog.application.dto.ArticleCommentDTO;
import com.ftf.tp.blog.application.dto.ArticleCommentPageDTO;
import com.ftf.tp.blog.application.dto.ArticleCommentReplyPageDTO;
import com.ftf.tp.blog.application.service.command.CommentCommandService;
import com.ftf.tp.blog.application.vo.ArticleCommentVO;
import com.ftf.tp.blog.domain.article.dos.ArticleCommentDO;
import com.ftf.tp.blog.domain.article.repository.ArticleRepository;
import com.ftf.tp.blog.domain.article.repository.CommentRepository;
import com.ftf.tp.common.constants.RedisConstant;
import com.ftf.tp.common.constants.RocketMqConstant;
import com.ftf.tp.common.core.exception.BusinessException;
import com.ftf.tp.common.core.redis.utils.RedissonHelper;
import com.ftf.tp.common.core.utils.SnowIdUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.redisson.client.protocol.ScoredEntry;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

/**
 * 评论service
 *
 * @author tanghao
 * @date 2021/12/20
 */
@Slf4j
@Service
public class CommentCommandServiceImpl implements CommentCommandService {

    @Resource
    private RocketMQTemplate rocketMQTemplate;


    @Resource
    private ArticleRepository articleRepository;

    @Resource
    private CommentRepository commentRepository;

    @Resource
    private RedissonHelper redissonHelper;

    /**
     * 评论文章
     *
     * @param blogComment 评论dto
     */
    @Override
    public void publishComment(ArticleCommentDTO blogComment) {
        //todo 先审核 审核通过在发布到mq
        blogComment.setCreatedTime(new Date());

        //todo 领域内spring异步事件 保存评论   -  影响文章上下文评论数 文章热度

        //todo 领域间 message 评论消息  user 用户经验
        rocketMQTemplate.syncSend(RocketMqConstant.PUBLISH_COMMENT_TOPIC, blogComment);


    }

    /**
     * 新增评论
     *
     * @param articleCommentDTO 评论实体
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addComment(ArticleCommentDTO articleCommentDTO) {
        try {
            ArticleCommentDO articleCommentDO = CommentAssembler.INSTANCE.dtoToDo(articleCommentDTO);
            Long id = SnowIdUtils.uniqueLong();
            articleCommentDO.setId(id);
            articleCommentDO.setCommentSupportNumber(0L);
            articleCommentDO.setCreatedTime(new Date());
            articleCommentDO.setUpdatedTime(new Date());
            ArticleCommentVO articleCommentVO =  CommentAssembler.INSTANCE.doToVo(articleCommentDO);
            Long blogId = articleCommentDTO.getArticleId();
            commentRepository.saveComment(articleCommentDO);
            //用来redis排序 根据时间  0.是为了后续根据点赞数排序 点赞数优于时间
            Double l = Double.parseDouble("0." + System.currentTimeMillis());
            if (articleCommentDTO.getCommentType().equals(0)) {
                redissonHelper.addZset(RedisConstant.REDIS_KEY_ARTICLE_COMMENT + ":" + blogId, articleCommentVO, l);
            } else {
                redissonHelper.addZset(RedisConstant.REDIS_KEY_ARTICLE_COMMENT_REPLY + ":" + articleCommentVO.getCommentParentId(), articleCommentVO, (double) 0);
            }
            //文章评论数+1
            articleRepository.commentBlog(RedisConstant.REDIS_KEY_ARTICLE_COMMENT_SUM + ":" + blogId, blogId);
            log.info("评论消息消费成功,{}", articleCommentDTO);
        } catch (Exception e) {
            //todo 出现异常 消息存库
            log.error("评论消息消费失败,{}", articleCommentDTO, e);
        }
    }

    /**
     * 获取文章的所有评论 以及评论的回复(两条)
     *
     * @param articleCommentPageDTO 文章评论分页参数
     */
    @Override
    public List<ArticleCommentVO> getCommentByBlogId(ArticleCommentPageDTO articleCommentPageDTO) {
        //获取所有的一级评论
        Collection<ScoredEntry<Object>> scanZset = redissonHelper.getScanZset(RedisConstant.REDIS_KEY_ARTICLE_COMMENT + ":" + articleCommentPageDTO.getArticleId(),
                (articleCommentPageDTO.getPage() - 1) * articleCommentPageDTO.getSize(),
                articleCommentPageDTO.getPage() * articleCommentPageDTO.getSize());
        List<ArticleCommentVO> articleCommentVOList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(scanZset)) {
            scanZset.forEach(comment -> {
                long supportSum = comment.getScore().longValue();
                ArticleCommentVO articleCommentVO = (ArticleCommentVO) comment.getValue();
                articleCommentVO.setCommentSupportNumber(supportSum);
                List<ArticleCommentVO> blogReplyList = new ArrayList<>();
                //获取该评论的2条回复
                Collection<ScoredEntry<Object>> scanZset1 = redissonHelper.getScanZset(RedisConstant.REDIS_KEY_ARTICLE_COMMENT_REPLY + ":" + articleCommentVO.getId(), 0, 1);
                if (CollectionUtils.isNotEmpty(scanZset1)) {
                    scanZset1.forEach(reply -> {
                        ArticleCommentVO replyVO = (ArticleCommentVO) reply.getValue();
                        replyVO.setCommentSupportNumber(reply.getScore().longValue());
                        blogReplyList.add(replyVO);
                    });
                    if (CollectionUtils.isNotEmpty(blogReplyList)) {
                        articleCommentVO.setArticleReplyList(blogReplyList);
                    }
                }
                articleCommentVOList.add(articleCommentVO);
            });
        } else {
            //todo 缓存是不过期的  当没取到数据 要么没有评论，要么redis崩了
        }
        return articleCommentVOList;
    }

    /**
     * 查看评论的所有回复
     *
     * @param articleCommentReplyPageDTO 文章回复分页参数
     */
    @Override
    public List<ArticleCommentVO> getReplyByCommentId(ArticleCommentReplyPageDTO articleCommentReplyPageDTO) {
        Collection<ScoredEntry<Object>> scanZset = redissonHelper.getScanZset(RedisConstant.REDIS_KEY_ARTICLE_COMMENT_REPLY + ":" + articleCommentReplyPageDTO.getCommentId(),
                (articleCommentReplyPageDTO.getPage() - 1) * articleCommentReplyPageDTO.getSize(),
                articleCommentReplyPageDTO.getPage() * articleCommentReplyPageDTO.getSize());
        List<ArticleCommentVO> articleCommentVOList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(scanZset)) {
            scanZset.forEach(comment -> {
                long supportSum = comment.getScore().longValue();
                ArticleCommentVO articleCommentVO = (ArticleCommentVO) comment.getValue();
                articleCommentVO.setCommentSupportNumber(supportSum);
                articleCommentVOList.add(articleCommentVO);
            });
        }
        return articleCommentVOList;
    }


    /**
     * 删除当前评论 未完成
     *
     * @param commentId   评论id
     * @param commentType 类型
     */
    @Override
    public void deleteCommentById(Long commentId, Integer commentType) {
        ArticleCommentDO articleCommentDO = commentRepository.byId(commentId);
        int rank = commentRepository.getRankById(commentId);
        if (ObjectUtils.isNotEmpty(articleCommentDO)) {
            String key = null;
            if (commentType.equals(0)) {
                key = RedisConstant.REDIS_KEY_ARTICLE_COMMENT + ":" + articleCommentDO.getArticleId();
            }
            if (commentType.equals(1)) {
                key = RedisConstant.REDIS_KEY_ARTICLE_COMMENT_REPLY + ":" + articleCommentDO.getCommentParentId();
            }
            if (redissonHelper.deleteZsetObject(key, rank - 1) > 0) {
                commentRepository.deleteById(commentId);
                log.info("评论删除成功,{}", commentId);
            } else {
                log.info("评论信息有误,{}", commentId);
            }
        } else {
            throw new BusinessException("评论已经删除或不存在");
        }
    }

}
